package yxy.game.login;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.joda.time.DateTime;
import yxy.apple.logger.Logger;
import yxy.apple.util.ActiveUtil;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.game.base.bean.GatewayUrl;
import yxy.cherry.game.base.bean.SDKParm;
import yxy.cherry.game.base.bean.SdkParmEnum;
import yxy.cherry.game.base.bean.UserBean;
import yxy.cherry.game.base.mq.MqMessage;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.bean.LoginOtherParm;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.area.CommonBean;
import yxy.game.pm2.bean.channel.SdkChannel;
import yxy.game.pm2.bean.cluster.ClusterBean;
import yxy.game.pm2.bean.db.dao.*;
import yxy.game.pm2.bean.db.module.*;
import yxy.game.pm2.bean.mq.MqMsg_AccountCreate;
import yxy.game.pm2.bean.mq.MqMsg_RoleCreate;
import yxy.game.pm2.bean.mq.MqMsg_RoleLogin;
import yxy.game.pm2.bean.sdk.ChannelControl;
import yxy.game.pm2.bean.sdk.ShengYeUploadServerid;
import yxy.game.pm2.bean.sdk.WeiXinOtherParm;
import yxy.game.sdk.shengye.Sdk_shengye;
import yxy.game.util.HttpUtil;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Random;

public class LoginModule {
    private static final Logger logger = Logger.create(LoginModule.class);

    public JSONObject login(String username, String password, String channel, String subchannel, String ip, LoginOtherParm otherparm) {
        long beginDebugTime = System.currentTimeMillis();
        logger.info("LoginModule:begin:" + username + ":" + beginDebugTime);
        JSONObject result = new JSONObject();

        int clusterId = otherparm.getClusterId();
        //旧包没clusterId参数，需要设置一个默认值
        if (clusterId == 0) clusterId = ClusterBean.defaultClusterId;
        ClusterBean clusterBean = ClusterBean.get(clusterId);
        logger.info("clusterId:" + clusterId);
        if (clusterBean == null) {
            return result(result, Error.Err_专服不存在);
        }

        if (username == null || password == null || username.length() == 0 || password.length() == 0) {
            return result(result, Error.Err_用户名错误);
        }

        if (!ChannelControl.canlogin(channel, subchannel)) {
            return result(result, Error.Err_渠道代码错误);
        }

        int isNewAccount = 0; //是否新账号，目前是用于小程序判断用
        Date now = DateTime.now().toDate();
        account db = MySQLAccountDAO.getByClusterId(username, clusterId);
        if (db == null) {
            isNewAccount = 1;

            db = new account();
            db.setClusterid(clusterId); //所属专服
            db.setName(username);
            db.setPassword(password);
            db.setChannel(channel);
            db.setSubchannel(subchannel);
            db.setCreateip(ip);
            db.setCreatetime(now);
            db.setLoginip(ip);
            db.setLogintime(now);
            // 创建账号
            MySQLAccountDAO.add(db);

            stat账号创建(db);
        } else {
            if (!db.getPassword().equals(password)) {
                return result(result, Error.Err_密码错误);
            }
            if (!(db.getChannel().equals(channel) || db.getSubchannel().equals(subchannel))) {
                return result(result, Error.Err_渠道代码错误);
            }
            // 封禁账号不让登录
            block _block = MySQLBlockDAO.get(db.getId());
            if (_block != null && _block.getEndTime().isAfter(LocalDateTime.now())) {
                result(result, Error.Err_账号被禁止登录);
                long endtime = _block.getEndTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                result.put("endtime", endtime);
                result.put("reason", _block.getReason());
                return result;
            }

            db.setLoginip(ip);
            db.setLogintime(now);
            // 更新账号
            MySQLAccountDAO.update(db);
        }
        try {
            //生成此次登录的token
            String token = UserBean.sign(RedisManager.getInstance().getConnection(RedisType.REDIS_USER), db.getId(), 3600);
            result.put("token", token);
        } catch (RedisException e) {
            return result(result, Error.Err_令牌失效);
        }

        result.put("accountId", db.getId());

        int roleSize = MySQLPlayerDAO.size(db.getId());
//		System.err.println("角色数：：：" + roleSize);
        result.put("roleSize", roleSize);

        // 封装推荐服务器 或 上次登录服务器
        server _server = MySQLServerDAO.get(db.getLastserverid());
        if (_server == null) {
            _server = MySQLServerDAO.getNew(clusterBean.getAreaList());
        }
        if (_server == null) {
            return result(result, Error.Err_服务器维护中);
        }
        result.put("server", _server);

        // 公告
        CommonBean commonBean = CommonBean.get(clusterId);
        result.put("notice", commonBean.getNotice());
        result.put("showQQ", commonBean.getShowQQ());
        result.put("showHaoPing", commonBean.getShowHaoPing());
        result.put("showJiaQun", commonBean.getShowJiaQun());
        result.put("isNewAccount", isNewAccount);

        specialDeal(channel, otherparm, db.getId(), _server);

        long endDebugTime = System.currentTimeMillis();
        logger.info("LoginModule:result:%s", result);
        logger.info("LoginModule:end:" + username + ":" + endDebugTime);
        logger.info("LoginModule:end:" + username + ":相差：" + (endDebugTime - beginDebugTime) + " 毫秒");

        return result(result, Error.OK);
    }

    public JSONObject servers(JSONObject request) {
        int accountId = request.getIntValue("accountId");
        String token = request.getString("token");
        logger.info("servers:" + JSON.toJSONString(request));
        logger.info("servers:begin:" + accountId + ":" + new Date().toString());

        JSONObject result = new JSONObject();

        try {
            //校验登录token
            if (!UserBean.verify(RedisManager.getInstance().getConnection(RedisType.REDIS_USER), accountId, token)) {
                return result(result, Error.Err_令牌失效);
            }
        } catch (RedisException e) {
            e.printStackTrace();
            return result(result, Error.Err_令牌失效);
        }

        account _account = MySQLAccountDAO.get(accountId);
        if (_account == null) {
            return result(result, Error.Err_角色不存在);
        }

        try {
            result.put("server", getServerInfo(_account));
        } catch (Exception e) {
            e.printStackTrace();
            return result(result, Error.Err_角色不存在);
        }
        logger.info("servers:end:" + accountId + ":" + new Date().toString());

        return result(result, Error.OK);
    }

    public static void main(String[] args) {
        System.out.println("servers:end:" + ":" + new Date().toString());
    }

    private JSONObject getServerInfo(account _account) throws Exception {
        List<server> list = MySQLServerDAO.getListByOpenTime(_account.getClusterid(), DateTime.now().toString());
        JSONObject info = new JSONObject();

        JSONArray listArray = new JSONArray();
        for (server db : list) {
            listArray.add(db);
        }

        info.put("list", listArray);

        info.put("roles", getPlayersInfo(_account));
        return info;
    }

    //登录游戏服，创角等
    public JSONObject game(JSONObject request) {
        logger.info("game:%s", request);
        int serverId = request.getIntValue("serverId");
        int accountId = request.getIntValue("accountId");
        String token = request.getString("token");

        JSONObject result = new JSONObject();

        try {
            if (!UserBean.verify(RedisManager.getInstance().getConnection(RedisType.REDIS_USER), accountId, token)) {
                return result(result, Error.Err_令牌失效);
            }
        } catch (RedisException e) {
            e.printStackTrace();
            return result(result, Error.Err_令牌失效);
        }

        Collection<String> urls = gatewayUrls();
        if (urls.size() <= 0) {
            return result(result, Error.Err_服务器维护中);
        }

        server _server = MySQLServerDAO.get(serverId);
        if (_server == null) {
            return result(result, Error.Err_服务器不存在);
        }

        try {
            account _account = MySQLAccountDAO.get(accountId);
            if (_account == null) {
                return result(result, Error.Err_角色不存在);
            }

            // 白名单
            boolean isWhite = checkWhite(_account, serverId);
            if (!isWhite) {
                if (_server.getOpenTime() != null) {
                    if (_server.getOpenTime().after(new Date())) {
                        result(result, Error.Err_服务器尚未开启);
                        if (_server.getOpenTip() != null) {
                            result.put("info", _server.getOpenTip());
                        }
                        return result;
                    }
                }
                if (_server.getState() == ServerState.STATE_維護.number()) {
                    result(result, Error.Err_服务器维护中);
                    if (_server.getOpenTip() != null) {
                        result.put("info", _server.getMaintainTips());
                    }
                    return result;
                }
            }

            // TODO 需要处理不能创建新角色的开关
            //如果服已开时间>3天,并且不属于新服，之前未创过角色则不能在该服创角
            player playerInfo = MySQLPlayerDAO.get(accountId, serverId);
//            DateTime dateTime = new DateTime(_server.getOpenTime());
//            DateTime now = DateTime.now();
//            if (playerInfo == null && ActiveUtil.days(dateTime, now) >= 3 && _server.getState() != ServerState.STATE_新服.number()) {
//                return result(result, Error.Err_开服时间超过10天不能创角色);
//            }

            player _player = getPlayer(accountId, serverId, playerInfo);

            UserBean.update(RedisManager.getInstance().getConnection(RedisType.REDIS_USER), accountId, serverId, _player.getCode(), 3600);

            result.put("playerCode", _player.getCode());
            result.put("gameUrls", urls);
            // 更新数据库
            _account.setLastserverid(serverId);
            MySQLAccountDAO.update(_account);
        } catch (RedisException e) {
            e.printStackTrace();
            return result(result, Error.Err_角色不存在);
        }
        logger.info("game:result:%s", request);
        return result(result, Error.OK);
    }

    //激活，埋点，统计数据用
    public JSONObject active(JSONObject request) {
        return request;
    }

    /**
     * 检查白名单
     */
    private boolean checkWhite(account _account, int serverId) {
        int count = MySQLWhiteListDAO.countByServerId(_account.getId(), serverId);
        return count < 1 ? false : true;
//		Collection<whitelist> whiteList = MySQLWhiteListDAO.get(_account.getId());
//		if (whiteList != null && whiteList.size() > 0) {
//			for (whitelist _whitelist : whiteList) {
//				if (_whitelist.getPlayerCode() == null || _whitelist.getPlayerCode().length() <= 0) {
//					return true;
//				}
//				player _player = MySQLPlayerDAO.get(_account.getId(), serverId);
//				if (_player == null) {
//					return false;
//				}
//				PlayerBean bean = PlayerBean.get(_player.getCode());
//				if (bean == null || !bean.getCode().equals(_whitelist.getPlayerCode())) {
//					return false;
//				}
//				return true;
//			}
//		}
//		return false;
    }

    //某个账号下的所有角色登录过的游戏服列表
    private JSONArray getPlayersInfo(account _account) throws RedisException {
        List<player> list = MySQLPlayerDAO.all(_account.getId());
        JSONArray info = new JSONArray();
        for (player _player : list) {
            JSONObject pinfo = getPlayerInfo(_player, _account.getLastserverid());
            if (pinfo != null) {
                info.add(pinfo);
            }
        }
        return info;
    }

    private player getPlayer(int uid, int serverId, player _player) throws RedisException {
        if (_player == null) {
            PlayerBean bean = PlayerBean.create(uid, serverId);
            _player = new player();
            _player.setAccountid(uid);
            _player.setServerid(serverId);
            _player.setCode(bean.getCode());
            MySQLPlayerDAO.add(_player);

            stat角色创建(bean);
        }
        PlayerBean bean = PlayerBean.get(_player.getCode());
        if (bean == null) {
            bean = PlayerBean.create(uid, serverId, _player.getCode());
        }

        stat角色登陆(bean);
        return _player;
    }

    private JSONObject getPlayerInfo(player _player, int lastserver) throws RedisException {
        PlayerBean bean = PlayerBean.get(_player.getCode());
        if (bean == null) {
            return null;
        }
        JSONObject playerInfo = new JSONObject();
        playerInfo.put("code", bean.getCode());
        playerInfo.put("name", bean.getName());
        playerInfo.put("level", bean.getLevel());
        playerInfo.put("vip", bean.getViplevel());
        playerInfo.put("serverId", _player.getServerid());
        server srv = MySQLServerDAO.get(_player.getServerid());
        playerInfo.put("sid", srv.getSid());
        if (_player.getServerid() == lastserver) {
            playerInfo.put("last", true);
        }
        return playerInfo;
    }

    public JSONObject result(JSONObject result, Error errcode) {
        result.put("result", errcode.number());
        return result;
    }

    private Collection<String> gatewayUrls() {
        return GatewayUrl.all(RedisManager.getInstance().getConnection(RedisType.REDIS_USER));
    }

    // 统计打点=====================================================================

    private void stat账号创建(account db) {
        MqMsg_AccountCreate msg = new MqMsg_AccountCreate();
        msg.setName(db.getName());
        msg.setUid(db.getId());
        msg.setTime(db.getCreatetime());
        msg.setChannel(db.getChannel());
        msg.setSubchannel(db.getSubchannel());
        MqMessage.sendMessage(msg);
    }

    private void stat角色创建(PlayerBean playerBean) {
        MqMsg_RoleCreate msg = new MqMsg_RoleCreate();
        msg.setCode(playerBean.getCode());
        msg.setUid(playerBean.getUid());
        msg.setServerid(playerBean.getServerId());
        msg.setTime(new Date());

        MqMessage.sendMessage(msg);
    }

    /**
     * 角色登录统计
     *
     * @param playerBean
     */
    private void stat角色登陆(PlayerBean playerBean) {
        MqMsg_RoleLogin msg = new MqMsg_RoleLogin();
        msg.setCode(playerBean.getCode());
        msg.setUid(playerBean.getUid());
        msg.setServerid(playerBean.getServerId());
        msg.setTime(new Date());

        MqMessage.sendMessage(msg);
    }

    /**
     * 存储 sdk/平台 特殊参数 特殊处理
     *
     * @param channel
     * @param otherparm
     */
    private void specialDeal(String channel, LoginOtherParm otherparm, int uid, server _server) {
        if (otherparm == null) {
            return;
        }

//		随机值
//		channel = SdkChannel.sdk_weixin;
//		otherparm = new LoginOtherParm(getRandomOfSize(6), getRandomOfSize(6), "0", "0", otherparm.getInvitecode());

        switch (channel) {
            case SdkChannel.sdk_weixin: {
                wxOtherParm(uid, otherparm);
//			WeiXinOtherParm wxop = WeiXinOtherParm.get(uid);
//			if (wxop == null) {
//				try {
//					try {
//						if (WeiXinOtherParm.lockWeiXinOtherParm()) {
//							WeiXinOtherParm module = new WeiXinOtherParm(uid, otherparm.getChannelopenid(), otherparm.getPlatuid(), otherparm.getAdid(),
//									otherparm.getInvitecode());
//							WeiXinOtherParm.touch().put(uid, module);
//						}
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					} finally {
//						WeiXinOtherParm.unlockWeiXinOtherParm();
//					}
//				} catch (RedisException e) {
//					e.printStackTrace();
//				}
//			} else {
//				if (wxop.getAdid() != null && wxop.getAdid().equals(otherparm.getAdid())) {
//
//				} else {
//					try {
//						if (WeiXinOtherParm.lockWeiXinOtherParm()) {
//							wxop.setAdid(otherparm.getAdid());
//							WeiXinOtherParm.touch().put(uid, wxop);
//						}
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					} catch (Exception e) {
//						e.printStackTrace();
//					} finally {
//						WeiXinOtherParm.unlockWeiXinOtherParm();
//					}
//				}
//			}
                break;
            }
            case SdkChannel.sdk_shengye: {
                wxOtherParm(uid, otherparm);
                shengyeReport(_server);

//			WeiXinOtherParm wxop = WeiXinOtherParm.get(uid);
//			if (wxop == null) {
//				try {
//					try {
//						if (WeiXinOtherParm.lockWeiXinOtherParm()) {
//							WeiXinOtherParm module = new WeiXinOtherParm(uid, otherparm.getChannelopenid(), otherparm.getPlatuid(), otherparm.getAdid(),
//									otherparm.getInvitecode());
//							WeiXinOtherParm.touch().put(uid, module);
//						}
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					} finally {
//						WeiXinOtherParm.unlockWeiXinOtherParm();
//					}
//				} catch (RedisException e) {
//					e.printStackTrace();
//				}
//			} else {
//				if (wxop.getAdid() != null && wxop.getAdid().equals(otherparm.getAdid())) {
//
//				} else {
//					try {
//						if (WeiXinOtherParm.lockWeiXinOtherParm()) {
//							wxop.setAdid(otherparm.getAdid());
//							WeiXinOtherParm.touch().put(uid, wxop);
//						}
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					} catch (Exception e) {
//						e.printStackTrace();
//					} finally {
//						WeiXinOtherParm.unlockWeiXinOtherParm();
//					}
//				}
//			}

//			//盛也上报区服
//			ShengYeUploadServerid moudle = ShengYeUploadServerid.get();
//			try {
//				if(moudle.tryLock()) {
//					int serverid = _server.getId();
//					if(!moudle.getServerids().contains(serverid)) {
//						//上报
////						请求⽅式: POST
////						参数名称 说明 是否必传
////						channel 当前所属游戏channel_id 是
////						server_id 游戏区服ID 是
////						server_name 游戏区服名称 是
////						create_time 游戏区服创建时间（时间戳int格式） 是
//						
//						JSONObject postjson = new JSONObject();
//						String channel_id = SDKParm.getSdkparmvalue(SdkParmEnum.shengye_gamekey);
//						int server_id = _server.getId();
//						String server_name = _server.getName();
//						
//						long opentime = _server.getOpenTime().getTime() / 1000;
//
//						int create_time = (int) opentime;
//						
//						postjson.put("channel", channel_id);
//						postjson.put("server_id", server_id);
//						postjson.put("server_name", server_name);
//						postjson.put("create_time", create_time);
//						
//						JSONObject returnjson = HttpUtil.response(Sdk_shengye.shengye_uploadserverid, 30000, postjson);
//						System.out.println("returnjson " + returnjson);
//											
//						if(returnjson != null && returnjson.size() != 0) {
////							//正确的请求回调
////							{
////								"status": 1001,
////								"info": "success"
////							}
//
//							int status = returnjson.getIntValue("status");
//							if(status == 1001) {
//								moudle.getServerids().add(_server.getId());
//								moudle.set();
//							}
//						}
//					}
// 				}
//			} catch (Exception e) {
//				e.printStackTrace();
//			} finally {
//				moudle.unlock();
//			}
                break;
            }
            default:
                break;
        }
    }

    private void wxOtherParm(int uid, LoginOtherParm otherparm) {
        WeiXinOtherParm wxop = WeiXinOtherParm.get(uid);
        if (wxop == null) {
            try {
                try {
                    if (WeiXinOtherParm.lockWeiXinOtherParm()) {
                        WeiXinOtherParm module = new WeiXinOtherParm(uid, otherparm.getChannelopenid(), otherparm.getPlatuid(), otherparm.getAdid(),
                                otherparm.getInvitecode());
                        WeiXinOtherParm.touch().put(uid, module);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    WeiXinOtherParm.unlockWeiXinOtherParm();
                }
            } catch (RedisException e) {
                e.printStackTrace();
            }
        } else {
            if (wxop.getAdid() != null && wxop.getAdid().equals(otherparm.getAdid())) {

            } else {
                try {
                    if (WeiXinOtherParm.lockWeiXinOtherParm()) {
                        wxop.setAdid(otherparm.getAdid());
                        WeiXinOtherParm.touch().put(uid, wxop);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    WeiXinOtherParm.unlockWeiXinOtherParm();
                }
            }
        }
    }

    private void shengyeReport(server _server) {
        // 盛也上报区服
        ShengYeUploadServerid moudle = ShengYeUploadServerid.get();
        try {
            if (moudle.tryLock()) {
                int serverid = _server.getId();
                if (!moudle.getServerids().contains(serverid)) {
                    // 上报
//					请求⽅式: POST
//					参数名称 说明 是否必传
//					channel 当前所属游戏channel_id 是
//					server_id 游戏区服ID 是
//					server_name 游戏区服名称 是
//					create_time 游戏区服创建时间（时间戳int格式） 是

                    JSONObject postjson = new JSONObject();
                    String channel_id = SDKParm.getSdkparmvalue(SdkParmEnum.shengye_gamekey);
                    int server_id = _server.getId();
                    String server_name = _server.getName();

                    long opentime = _server.getOpenTime().getTime() / 1000;

                    int create_time = (int) opentime;

                    postjson.put("channel", channel_id);
                    postjson.put("server_id", server_id);
                    postjson.put("server_name", server_name);
                    postjson.put("create_time", create_time);

                    JSONObject returnjson = HttpUtil.response(Sdk_shengye.shengye_uploadserverid, 30000, postjson);
                    System.out.println("returnjson " + returnjson);

                    if (returnjson != null && returnjson.size() != 0) {
//						//正确的请求回调
//						{
//							"status": 1001,
//							"info": "success"
//						}

                        int status = returnjson.getIntValue("status");
                        if (status == 1001) {
                            moudle.getServerids().add(_server.getId());
                            moudle.set();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            moudle.unlock();
        }
    }

    /**
     * 产生几位随机数
     *
     * @return
     */
    public static String getRandomOfSize(int size) {
        Random rad = new Random();
        int limits = (int) Math.pow(10, size);
        String result = rad.nextInt(limits) + "";
        if (result.length() < size) {
            String adds = "";
            for (int i = 0; i < size - result.length(); i++) {
                adds = adds + "0";
            }
            result = adds + result;
        }
        return result;
    }
}
